home *** CD-ROM | disk | FTP | other *** search
Java Source | 1996-05-21 | 11.6 KB | 371 lines |
- /*
- * @(#)/XSliceVolumeFilter.java 1.4 96/03/31 by Andrew Barclay abb@nuccard.eushc.org
- *
- * Copyright (c) 1995 Andrew B. Barclay All Rights Reserved.
- */
-
- import java.awt.image.ColorModel ;
- import java.awt.image.ImageConsumer ;
- import java.awt.image.ImageProducer ;
- import java.awt.Point ;
- import java.awt.Rectangle ;
-
- import SliceVolumeFilter ;
-
- /**
- * An ImageFilter class for sliceing volume images.
- * This class extends the basic ImageFilter Class to extract a given
- * slice of an existing Volume and provide a source for a
- * new image containing just the extracted slice. It is meant to
- * be used in conjunction with a FilteredImageSource object to produce
- * sliced versions of existing volumes.
- *
- * This one's a bear, because the image granularity is 1 pixel. After
- * endless trials (really) I've resorted to just waiting for complete
- * scanlines before updating. Random pixel delivery to the dithering
- * engine produces unpredictable results.
- *
- * @see CropImageFilter
- * @see FilteredImageSource
- * @see ImageFilter
- * @see SliceVolumeFilter
- *
- * @version 1.4 96/03/31
- * @author Andrew Barclay
- */
-
- public class XSliceVolumeFilter extends SliceVolumeFilter {
- public byte dpixbyte[] ; // byte extracted pixel buffer
- public int dpixint[] ; // int extracted pixel buffer
- double szincr ; // source z-increment for each dest. z slice
- int nslices ;
- int hints ;
- int completecols[] ;
- int completerows ;
- ColorModel colormodel ; // last colormodel (for resends)
-
- synchronized void dbg( String s ) {
- if( false ) {
- System.out.println( s ) ;
- }
- }
-
- /**
- * Construct a SliceVolumeFilter that extracts a slice of the source
- * Volume specified by the ul, ll and ur parameters.
- * @param srcSlices[] the array of x,y positions of the source image slices
- * @param volWidth the width of the source volume
- * @param volHeight the height of the source volume
- * @param slice the slice number to be extracted
- * @param width the width of the slice to be extracted
- * @param height the height of the slice to be extracted
- */
- public XSliceVolumeFilter( Point srcSlices[], int volWidth,
- int volHeight, double slice, int width, int height ) {
- super( srcSlices, volWidth, volHeight, slice, width, height ) ;
- type = 'X' ;
- szincr = (double)voldims[2] / (double)width ; // usually 1.0
- nslices = voldims[0] ;
- hints = 0 ;
- completecols = new int[height] ;
- for( int i = 0 ; i < height ; i++ ) {
- completecols[i] = 0 ;
- }
- completerows = 0 ;
- }
-
- public void resendTopDownLeftRight( ImageProducer ip ) {
- dbg( "resendTopDownLeftRight called." ) ;
- if( dpixbyte != null ) {
- setConsumerPixels( 0, 0, width, height,
- this.colormodel, dpixbyte, 0, width ) ;
- } else if( dpixint != null ) {
- setConsumerPixels( 0, 0, width, height,
- this.colormodel, dpixint, 0, width ) ;
- }
- }
-
- public void setHints( int hints ) {
- this.hints = hints ;
- dbg( "setHints called, COMPLETESCANLINES="+((hints&ImageConsumer.COMPLETESCANLINES)!=0)+", RANDOMPIXELORDER="+((hints&ImageConsumer.RANDOMPIXELORDER)!=0) ) ;
- dbg( "SINGLEPASS="+((hints&ImageConsumer.SINGLEPASS)!=0)+", SINGLEFRAME="+((hints&ImageConsumer.SINGLEFRAME)!=0) ) ;
- }
-
- /**
- * Decide if we can deliver complete scanlines before sending
- * pixels to consumer.
- */
- public void setConsumerPixels( int sx, int sy, int sw, int sh,
- ColorModel colormodel, byte spix[], int soff,
- int sscansize ) {
- if( sw != width ) {
- /*
- * The code below doesn't work and is very cpu intensive.
- * I suspect that the API cannot handle RANDOMPIXELORDER.
- *
- * Random delivery code:
- * In this case, clear all other hints so the consumer
- * will request a resend. The next time through we
- * should have complete scanlines, etc.
- *
- hints = ImageConsumer.RANDOMPIXELORDER ;
- consumer.setHints( hints ) ;
- consumer.setPixels( sx, sy, sw, sh, colormodel,
- spix, soff, sscansize ) ;
- */
-
- dbg( "g.setConsumerPixels.byte: sx="+sx+" sy="+sy+" sw="+sw+" sh="+sh+"." ) ;
- for( int y = sy ; y < sy+sh ; y++ ) {
- completecols[y] += sw ;
- if( completecols[y] == width ) {
- completerows++ ;
-
- /*
- * This doesn't work either -- just get a blank image,
- * though I'm delivering real data to the consumer???
- *
- // spit complete line out.
- int p = y*width ;
- byte max = spix[p++] ;
- for( int i = 1 ; i < width ; i++ ) {
- if( spix[p] > max ) max = spix[p] ;
- p++ ;
- }
- System.out.println( "completed line "+y+" max="+max+"." ) ;
- //consumer.setHints( COMPLETESCANLINES|SINGLEPASS|SINGLEFRAME ) ;
- consumer.setHints( hints ) ;
- consumer.setPixels( 0, y, width, 1, colormodel,
- spix, soff, sscansize ) ;
- */
- }
- }
-
- /*
- * Full buffering is the only way it works reliably.
- */
- if( completerows == height ) {
- consumer.setHints( hints ) ;
- consumer.setPixels( 0, 0, width, height,
- colormodel, dpixbyte, 0, width ) ;
- }
- } else {
- dbg( "setConsumerPixels.byte: sw==width="+sw+".") ;
- consumer.setHints( hints ) ;
- consumer.setPixels( sx, sy, sw, sh, colormodel,
- spix, soff, sscansize ) ;
- }
- }
-
- public void setConsumerPixels( int sx, int sy, int sw, int sh,
- ColorModel colormodel, int spix[], int soff,
- int sscansize ) {
- if( sw != width ) {
- dbg( "g.setConsumerPixels.int: sx="+sx+" sy="+sy+" sw="+sw+" sh="+sh+"." ) ;
- for( int y = sy ; y < sy+sh ; y++ ) {
- completecols[y] += sw ;
- if( completecols[y] == width ) {
- completerows++ ;
- }
- }
-
- /*
- * Full buffering is the only way it works reliably.
- */
- if( completerows == height ) {
- consumer.setHints( hints ) ;
- consumer.setPixels( 0, 0, width, height,
- colormodel, dpixint, 0, width ) ;
- }
- } else {
- dbg( "setConsumerPixels.int: sw==width="+sw+".") ;
- consumer.setHints( hints ) ;
- consumer.setPixels( sx, sy, sw, sh, colormodel,
- spix, soff, sscansize ) ;
- }
- }
-
- /**
- * Determine if the delivered pixels intersect the slice to
- * be extracted and pass through only that subset of pixels that
- * appear in the output slice.
- */
- public void setPixels( int sx, int sy, int sw, int sh,
- ColorModel colormodel, byte spix[], int soff,
- int sscansize ) {
- long ct = System.currentTimeMillis() ;
- Rectangle sr = new Rectangle( sx, sy, sw, sh ) ;
- int sz1 = firstZSlice( sr ) ; // first z-slice intersecting region
- int sz2 = lastZSlice( sr ) ; // last z-slice intersecting region
- this.colormodel = colormodel ;
- /*
- dbg( "sr="+sr+" sz1="+sz1+" sz2="+sz2 ) ;
- dbg( "off="+soff+" scansize="+sscansize+" type="+type+" slice="+slice ) ;
- */
-
- // implement this generally later -- for now, just take orthogonal
- // slices.
- int islice = (int)( 0.5 + slice ) ;
- if( islice >= 0 && islice < nslices ) {
- // fix later: the allocation should depend on szincr too...
- if( dpixbyte == null ) {
- dpixbyte = new byte[width*height] ;
- }
- double sz ;
- int ncols = 0 ;
- int lastxstart = 0, lastystart = 0, lastyend = 0 ;
-
- for( sz = -0.5*szincr + sz1 ; sz < (-0.5 + sz2) ; sz += szincr ) {
- // z-coords in source correspond to x-coords in dest.
- int xstart = (int)( 0.5 + sz/szincr ) ;
- int isz = (int)( 0.5 + sz ) ;
- int x1 = srcSlices[isz].x + islice ;
- int y1 = srcSlices[isz].y ;
- if( sy < (y1+height) && (sy+sh) > y1 &&
- sx <= x1 && (sx+sw) > x1 ) {
-
- int ystart = (y1>=sy) ? 0 : sy-y1 ;
- int yend = ((y1+height)>(sy+sh)) ? (sy+sh-y1) : height ;
- int is = soff + (x1-sx) + (y1+ystart-sy)*sscansize ;
- int id = xstart + ystart*width ;
-
- // Copy portion of column from the source to dest.
- for( int dy = ystart ; dy < yend ; dy++ ) {
- dpixbyte[id] = spix[is] ;
- is += sscansize ;
- id += width ;
- }
-
- if( ncols == 0 ) {
- // initialize these.
- lastxstart = xstart ;
- lastystart = ystart ;
- lastyend = yend ;
- ncols = 1 ;
- } else if( lastystart != ystart || lastyend != yend ) {
- // spit out columns up to this column.
- setConsumerPixels( lastxstart, lastystart, ncols,
- lastyend-lastystart, colormodel, dpixbyte,
- 0, width ) ;
-
- lastxstart = xstart ;
- lastystart = ystart ;
- lastyend = yend ;
- ncols = 1 ;
- } else {
- ncols++ ;
- }
- } else if( ncols > 0 ) {
- // probably skipping a z-slice, spit out columns up
- // to this column.
- setConsumerPixels( lastxstart, lastystart, ncols,
- lastyend-lastystart, colormodel, dpixbyte,
- 0, width ) ;
- ncols = 0 ;
- }
- }
-
- // spit out remaining columns.
- if( ncols > 0 ) {
- setConsumerPixels( lastxstart, lastystart, ncols,
- lastyend-lastystart, colormodel, dpixbyte,
- 0, width ) ;
-
- dbg( "byte time= "+(System.currentTimeMillis()-ct)+" ms.\n" ) ;
- dbg( "xslice="+islice+" sr="+sr+" sz1="+sz1+" sz2="+sz2 ) ;
- dbg( "lastxstart="+lastxstart+" ncols="+ncols ) ;
- dbg( "lastystart="+lastystart+" lastyend="+lastyend ) ;
- }
- }
- }
-
- public void setPixels( int sx, int sy, int sw, int sh,
- ColorModel colormodel, int spix[], int soff,
- int sscansize ) {
- long ct = System.currentTimeMillis() ;
- Rectangle sr = new Rectangle( sx, sy, sw, sh ) ;
- int sz1 = firstZSlice( sr ) ; // first z-slice intersecting region
- int sz2 = lastZSlice( sr ) ; // last z-slice intersecting region
- this.colormodel = colormodel ;
- /*
- dbg( "sr="+sr+" sz1="+sz1+" sz2="+sz2 ) ;
- dbg( "off="+soff+" scansize="+sscansize+" type="+type+" slice="+slice ) ;
- */
-
- // implement this generally later -- for now, just take orthogonal
- // slices.
- int islice = (int)( 0.5 + slice ) ;
- if( islice >= 0 && islice < nslices ) {
- // fix later: the allocation should depend on szincr too...
- if( dpixint == null ) {
- dpixint = new int[width*height] ;
- }
- double sz ;
- int ncols = 0 ;
- int lastxstart = 0, lastystart = 0, lastyend = 0 ;
-
- for( sz = -0.5*szincr + sz1 ; sz < (-0.5 + sz2) ; sz += szincr ) {
- // z-coords in source correspond to x-coords in dest.
- int xstart = (int)( 0.5 + sz/szincr ) ;
- int isz = (int)( 0.5 + sz ) ;
- int x1 = srcSlices[isz].x + islice ;
- int y1 = srcSlices[isz].y ;
- if( sy < (y1+height) && (sy+sh) > y1 &&
- sx <= x1 && (sx+sw) > x1 ) {
-
- int ystart = (y1>=sy) ? 0 : sy-y1 ;
- int yend = ((y1+height)>(sy+sh)) ? (sy+sh-y1) : height ;
- int is = soff + (x1-sx) + (y1+ystart-sy)*sscansize ;
- int id = xstart + ystart*width ;
-
- // Copy portion of column from the source to dest.
- for( int dy = ystart ; dy < yend ; dy++ ) {
- dpixint[id] = spix[is] ;
- is += sscansize ;
- id += width ;
- }
-
- if( ncols == 0 ) {
- // initialize these.
- lastxstart = xstart ;
- lastystart = ystart ;
- lastyend = yend ;
- ncols = 1 ;
- } else if( lastystart != ystart || lastyend != yend ) {
- // spit out columns up to this column.
- setConsumerPixels( lastxstart, lastystart, ncols,
- lastyend-lastystart, colormodel, dpixint,
- 0, width ) ;
-
- lastxstart = xstart ;
- lastystart = ystart ;
- lastyend = yend ;
- ncols = 1 ;
- } else {
- ncols++ ;
- }
- } else if( ncols > 0 ) {
- // probably skipping a z-slice, spit out columns up
- // to this column.
- setConsumerPixels( lastxstart, lastystart, ncols,
- lastyend-lastystart, colormodel, dpixint,
- 0, width ) ;
- ncols = 0 ;
- }
- }
-
- // spit out remaining columns.
- if( ncols > 0 ) {
- setConsumerPixels( lastxstart, lastystart, ncols,
- lastyend-lastystart, colormodel, dpixint,
- 0, width ) ;
-
- dbg( "int time= "+(System.currentTimeMillis()-ct)+" ms.\n" ) ;
- dbg( "xslice="+islice+" sr="+sr+" sz1="+sz1+" sz2="+sz2 ) ;
- dbg( "lastxstart="+lastxstart+" ncols="+ncols ) ;
- dbg( "lastystart="+lastystart+" lastyend="+lastyend ) ;
- }
- }
- }
-
- }
-